package com.inspur.edp.bef.bemanager.generatedbo;

import com.inspur.edp.bef.bemanager.util.DataValidatorUtil;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.bef.bizentity.util.DboTransferUtil;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.lcm.databaseobject.api.DatabaseObjectServiceForWebIde;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectColumn;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectTable;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectTableCore;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectType;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectView;
import lombok.var;

import java.util.UUID;

public class GenerateFromDbo {

    public static GenerateFromDbo getInstance() {
        return new GenerateFromDbo();
    }

    private final String exceptionCode = "BeGenerateDbo";
    private final DatabaseObjectServiceForWebIde dtService = SpringBeanUtils.getBean(DatabaseObjectServiceForWebIde.class);
    private final MetadataProjectService projectService = SpringBeanUtils.getBean(MetadataProjectService.class);

    private GenerateFromDbo() {
    }

    public final GspBizEntityObject convertDboToBizObject(String path, String dboId, String primaryKey) {
        DataValidatorUtil.CheckForEmptyString(path, "path");
        DataValidatorUtil.CheckForEmptyString(dboId, "dboId");
        DataValidatorUtil.CheckForEmptyString(primaryKey, "primaryKey");
        DatabaseObjectTableCore dbo = GetDatabaseObjectTable(path, dboId);
        return convertDboToBizObject(dbo, primaryKey);
    }

    //ORIGINAL LINE: public GspElementCollection ConvertDboColumnsToElements(string path, string dboId, IList<string> columnIds, IGspCommonObject parentObject = null)
    public final GspElementCollection ConvertDboColumnsToElements(String path, String dboId, java.util.List<String> columnIds, IGspCommonObject parentObject) {
        DataValidatorUtil.CheckForNullReference(columnIds, "columnIds");
        DataValidatorUtil.CheckForEmptyString(path, "path");
        DataValidatorUtil.CheckForEmptyString(dboId, "dboId");
        GspElementCollection elements = new GspElementCollection(parentObject);
        if (columnIds.isEmpty()) {
            return elements;
        }
        DatabaseObjectTableCore dbo = GetDatabaseObjectTable(path, dboId);
        for (String columnId : columnIds) {
            try {
                boolean isMulti = getIsMultiColumn(dbo, columnId);
                GspBizEntityElement ele = convertDboColumnToBizElement(dbo.getColumnById(columnId), isMulti);
                elements.add(ele);
            } catch (RuntimeException e) {
                continue;
            }

        }
        return elements;
    }

    private GspBizEntityObject convertDboToBizObject(DatabaseObjectTableCore dbo, String primaryKey) {
        DataValidatorUtil.CheckForNullReference(dbo, "dbo");
        DataValidatorUtil.CheckForNullReference(primaryKey, "primaryKey");
        GspBizEntityObject obj = new GspBizEntityObject();
        obj.setID(UUID.randomUUID().toString());
        obj.setCode(dbo.getCode());
        obj.setName(dbo.getName());
        obj.setRefObjectName(dbo.getId());
        obj.setObjectType(GspCommonObjectType.MainObject);
        boolean hasSetPrimaryKey = false;
        // 主键
        for (DatabaseObjectColumn column : dbo.getColumns()) {
            boolean isMulti = getIsMultiColumn(dbo, column.getId());
            try {
                GspBizEntityElement ele = convertDboColumnToBizElement(column, isMulti);
                obj.getContainElements().add(ele);
                if (primaryKey.equals(column.getId())) {
                    obj.getColumnGenerateID().setElementID(ele.getID());
                    ele.setIsRequire(true);
                    String IDElementLabelId = "ID";
                    if (!IDElementLabelId.equals(ele.getLabelID())) {
                        ele.setLabelID(IDElementLabelId);
                    }
                    ele.setCode(IDElementLabelId);
                    ele.setName(IDElementLabelId);
                    hasSetPrimaryKey = true;
                }
            } catch (Exception e) {
                //TODO 此处Catch异常需要确认
                throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0040, e);
            }

        }

        if (!hasSetPrimaryKey) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0041, dbo.getId(), primaryKey);
        }
        return obj;
    }

    private GspBizEntityElement convertDboColumnToBizElement(DatabaseObjectColumn column, boolean isMulti) {
        GspBizEntityElement ele = new GspBizEntityElement();
        ele.setID(UUID.randomUUID().toString());
        ele.setLabelID(column.getCode());
        ele.setCode(column.getCode());
        ele.setName(column.getName());
        ele.setColumnID(column.getId());
        ele.setMDataType(DboTransferUtil.getMDataTypeByDataType(column.getDataType(),exceptionCode));
        RefObject<Integer> length = new RefObject<>(0);
        RefObject<Integer> precision = new RefObject<>(0);
        getLengthPrecisionScale(column, length, precision);
        ele.setLength(length.argvalue);
        ele.setPrecision(precision.argvalue);
        ele.setIsRequire(!column.isNullable());
        ele.setIsMultiLanguage(isMulti);
        return ele;
    }

    private DatabaseObjectTableCore GetDatabaseObjectTable(String path, String dboId) {

        var dbo = dtService.getDatabaseObjectById(path, dboId);
//        if (!(dbo instanceof DatabaseObjectTable)) {
//            throw new RuntimeException("根据路径" + path + "及" + dboId + "获取dbo元数据失败。");
//        }
        if (dbo==null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0049, path, dboId);
        }
        return (DatabaseObjectTableCore) dbo;
    }

    /**
     * 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
     *
     * @param column    数据库对象列
     * @param length    column中长度
     * @param precision column中精度
     */
    private void getLengthPrecisionScale(DatabaseObjectColumn column, RefObject<Integer> length, RefObject<Integer> precision) {
        GspElementDataType mdataType = DboTransferUtil.getMDataTypeByDataType(column.getDataType(),exceptionCode);
        length.argvalue = 0;
        precision.argvalue = 0;

        // 解决lcm的长度精度小数位数与beElementDataType中长度精度小数位数中表达不一致问题
        switch (mdataType) {
            case String:
                length.argvalue = column.getLength();
                precision.argvalue = 0;
                break;
            case Decimal:
                length.argvalue = column.getPrecision();
                // BE浮点型字段精度不允许为0
                precision.argvalue = column.getScale() == 0 ? 2 : column.getScale();
                break;
            case Boolean:
                length.argvalue = 1;
                precision.argvalue = 0;
                break;
            // 其他 0，0
        }
    }

    private boolean getIsMultiColumn(DatabaseObjectTableCore dbo, String columnId) {
        boolean isExistColumnId = false;
        if(dbo.getType()==DatabaseObjectType.Table){
            for (String item :((DatabaseObjectTable)dbo).getMultiLanguageColumns()) {
                if (item != null && item.equals(columnId)) {
                    isExistColumnId = true;
                    break;
                }
            }
            isExistColumnId= ((DatabaseObjectTable)dbo).isI18NObject() && isExistColumnId;
        }
        if(dbo.getType()==DatabaseObjectType.View){

            for (String item : ((DatabaseObjectView)dbo).getMultiLanguageColumns()) {
                if (item != null && item.equals(columnId)) {
                    isExistColumnId = true;
                    break;
                }
            }

            isExistColumnId= ((DatabaseObjectView)dbo).isI18nObject() && isExistColumnId;
        }
        return isExistColumnId;

    }

    /**
     * 节点编号-dbo编号去除[关键应用]前缀
     *
     * @param
     * @return
     */
    private String getObjectCodeWithDboName(String dboCode, String metapath) {
        String appCode = GetAppCode(metapath);
        String strRegex = "^(" + appCode + ")";

//        String result = Regex.Replace(dboCode, strRegex, "");
        String result = strRegex.replace(dboCode, "");
        if (result.length() > 0) {
            return result;
        }
        return dboCode;
    }

    MetadataService service = SpringBeanUtils.getBean(MetadataService.class);

    public String GetAppCode(String metadataPath) {

        var projectPath = projectService.getMetadataProjInfo(metadataPath).getProjectPath();
        ;
        return this.service.getGspProjectInfo(projectPath).getAppCode();
    }
}
